<template>
  <div class="init-container">
    <Input
      border
      type="text"
      readonly
      :value="showVal"
      :placeholder="$srv.getI18nByValue('点击右侧图标编辑')"
    >
      <Icon type="ios-book-outline" slot="suffix" @click="openEditor" />
    </Input>
    <o-dialog-box
      v-model="visible"
      width="800"
      @on-ok="onOK"
      :cancelText="$srv.getI18nByValue('取消编辑')"
      :okText="$srv.getI18nByValue('确认')"
    >
      <ckeditor
        :id="editorID"
        slot="content"
        :editor="editor"
        v-model="G_value"
        :disabled="renderOpts.props.disabled"
        :config="editorConfig"
        @ready="initExtraPlugins"
      ></ckeditor>
    </o-dialog-box>
  </div>
</template>

<script lang="ts">
import { T_srv, Tsrv, ifs, ts, vue } from '@/services';
import { N_input } from '@/types';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import '@ckeditor/ckeditor5-build-classic/build/translations/en-au';
import '@ckeditor/ckeditor5-build-classic/build/translations/zh';
import '@ckeditor/ckeditor5-build-classic/build/translations/zh-cn';
// import {
//   Image,
//   ImageResizeEditing,
//   ImageResizeHandles
// } from '@ckeditor/ckeditor5-image';
import '@ckeditor/ckeditor5-ui/theme/mixins/_dir.css';
import { ImageUploadAdapter } from './imageUploadAdapter';

@T_srv.comp({
  components: {}
})
export default class oRichText extends vue {
  /* 父组件compBoxInfo */
  @T_srv.prop({
    required: false,
    type: Object,
    default: null
  })
  compBoxInfo: ifs.I_compBoxInfo;

  @T_srv.prop() renderOpts: N_input.I_renderOpts;

  @T_srv.prop() params: any;

  /* 组件名 */
  private name: string = 'oRichText';

  private G_compName: string = this.name;

  /* 组件箱信息对象 */
  private GT_compBoxInfo: ifs.I_compBoxInfo;

  /* 组件箱对象 */
  private GT_compBox: ifs.I_compBox;

  /* 组件箱识别ID */
  private G_compID: string;

  /* 指挥部 */
  /* 遮罩 */
  public isMask: boolean = false;

  public G_value: string = '';

  public showVal: string = '';

  public editor = ClassicEditor;

  public visible: boolean = false;

  private editorID: string = Tsrv.utils.custUUID(8);

  private fileLibID: string = '';

  public editorConfig = {
    language:
      this.$i18n.locale === Tsrv.globalVar.i18n.zhCN
        ? 'zh-cn'
        : this.$i18n.locale === Tsrv.globalVar.i18n.zhTW
        ? 'zh'
        : 'en-au'
    // simpleUpload: {
    //   // The URL that the images are uploaded to.
    //   uploadUrl: 'http://example.com',

    //   // Enable the XMLHttpRequest.withCredentials property.
    //   withCredentials: true,

    //   // Headers sent along with the XMLHttpRequest to the upload server.
    //   headers: {
    //     'X-CSRF-TOKEN': 'CSRF-Token',
    //     Authorization: 'Bearer <JSON Web Token>'
    //   }
    // }
  };

  private G_paramsFromComp: string = null;

  private fileNames: Set<string> = new Set();

  @T_srv.model('model-change') modelvalue: string | null;

  @T_srv.watch('modelvalue')
  private onValueChange(val: string | null): void {
    this.setValue(val);
  }

  @T_srv.watch('params')
  onParamsChange(val) {
    this.handleParams();
  }

  created() {
    // 如果父组件没有传参，那就产生一个
    this.GT_compBoxInfo = Tsrv.getCompInfo(this.compBoxInfo);
    this.G_compID = this.GT_compBoxInfo.compID;
    this.GT_compBox = this.GT_compBoxInfo.TcompBox;
    this.init();
  }

  mounted() {
    /* 向父组件发送实例 */
    this.GT_compBox.addCompMergeName(this.G_compID, this.G_compName, this);
    this.$emit('compBoxInfo', this.GT_compBoxInfo);
  }

  destroyed() {
    /* 注册组件销毁 */
    this.GT_compBox.removeCompMergeName(this.G_compID, this.G_compName);

    /* 如果父组件传入的compBoxInfo则删除本文件产生的引用,反之是本组件产生的ID统一删除 */
    if (Tsrv.utils.isEmpty(this.compBoxInfo)) {
      this.GT_compBox.removeCompsWithCompID(this.G_compID);
    } else {
      this.GT_compBox.removeCompsMergeName(this.G_compID, [
        `'${this.G_compName}'`
      ]);
    }
  }

  public resetValue(): void {
    this.setValue(null);
  }

  public setValue(val: string): void {
    if (Tsrv.utils.noValue(val)) {
      this.G_value = '';
    }
    this.setShowVal();
    this.setParamsData();
    this.emitEvent('dochange');
  }

  public setParamsData(): void {
    const pData = JSON.stringify({
      fileLibID: this.fileLibID,
      nfsFileNames: Array.from(this.fileNames),
      content: Tsrv.utils.compressString(this.G_value)
    });
    if (this.G_paramsFromComp === 'oBaseGrid') {
      this.params.row[this.params.column.property] = pData;
    } else {
      this.params.data[this.params.property] = pData;
    }
  }

  public emitEvent(event: string): void {
    const ev: any = this.renderOpts.events;
    const params = Tsrv.utils.cloneNoMatchVue(this.params, true);
    params.from = 'inputtext';
    for (const action in ev) {
      if (ev[action] && action === `on-${event}`) {
        ev[action](params);
      }
    }
    this.$emit('model-change', this.G_value);
    this.$emit('on-change', this.G_value);
  }

  private init() {
    this.G_paramsFromComp = this.renderOpts.props.getTcommand()?.compName;
    if (Tsrv.noValue(this.G_paramsFromComp)) {
      this.$msg(Tsrv.getI18nByValue('未定义的组件'));
      console.error('未定义的组件');
    }
    this.handleParams();
  }

  private handleParams() {
    if (Tsrv.noValue(this.G_value)) {
      let val;
      if (this.G_paramsFromComp === 'oBaseGrid') {
        val = this.params.row[this.params.column.property];
      } else {
        val = this.params.data[this.params.property];
      }
      if (!Tsrv.utils.noValue(val)) {
        const v = JSON.parse(val);
        v.nfsFileNames.forEach(ele => {
          this.fileNames.add(ele);
        });
        this.fileLibID = v.fileLibID;
        this.G_value = Tsrv.utils.decompressString(v.content);
      }
      this.setShowVal();
    }
  }

  public setShowVal() {
    if (!Tsrv.utils.noValue(this.G_value)) {
      const s = this.G_value.replace(/<[^>]+>/g, '')
        .replace(/&nbsp;/g, '')
        .substring(0, 20);
      if (s.length > 0) {
        this.showVal = `${s}...`;
      }
      this.showVal = s;
    }
  }

  public openEditor() {
    this.visible = true;
  }

  public onOK() {
    this.setValue(this.G_value);
  }

  private uploadUrlHandler(blobInfo) {
    return new Promise((resolve, reject) => {
      const upd = new ts.T_uploadArg(Tsrv.getWsCliID());
      upd.setType('image').setFiles(blobInfo.blob());
      upd.SetRouteID(Tsrv.utils.custUUID());
      Tsrv.upLoad(upd).then(([res, err]) => {
        this.$msg(err ?? res.msg);
        // if (res.success) {
        // }
      });
    });
  }

  public initExtraPlugins(editor: any) {
    editor.plugins.get('FileRepository').createUploadAdapter = (
      loader: any
    ) => {
      return new ImageUploadAdapter(loader, this);
    };
    editor.model.document.on('change', e => {
      const chgContent = e.source.differ.getChanges();
      if (Array.isArray(chgContent) && !Tsrv.utils.noValue(chgContent)) {
        chgContent.forEach(el => {
          // 增加图片
          if (
            el.type === 'attribute' &&
            el.attributeKey === 'src' &&
            !Tsrv.utils.noValue(el.attributeNewValue)
          ) {
            const url = new URLSearchParams(
              new URL(el.attributeNewValue).search
            );
            const imageName = url.get(`fileName`);
            if (Tsrv.utils.noValue(imageName)) {
              this.$msg(Tsrv.getI18nByValue('插入图片时未获取到文件名'));
              throw new Error('插入图片时未获取到文件名');
            }
            this.fileNames.add(imageName);
            console.info('add', imageName);
            // 删除图片
          } else if (el.type === 'remove' && el.name === 'imageBlock') {
            if (el.attributes instanceof Map) {
              const url = new URLSearchParams(
                new URL(el.attributes.get(`src`)).search
              );
              const imageName = url.get(`fileName`);
              if (Tsrv.utils.noValue(imageName)) {
                this.$msg(Tsrv.getI18nByValue('删除图片时未获取到文件名'));
                throw new Error('插入图片时未获取到文件名');
              }
              this.fileNames.delete(imageName);
              console.info('delete', imageName);
            }
          }
        });
      }
    });
  }
}
</script>
<style lang="scss" scoped>
.editor-container {
  padding: 6px;
  position: absolute;
  width: 200px;
  height: 100px;
  top: 0;
  left: 0;
}
</style>
